package com.jrx.anytxn.param.service.system.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.BeanMapping;
import com.jrx.anytxn.i18n.response.TxnPage;
import com.jrx.anytxn.number.exception.SegmentException;
import com.jrx.anytxn.number.service.ISegmentService;
import com.jrx.anytxn.param.constant.Constant;
import com.jrx.anytxn.param.constant.ErrorMsgConstant;
import com.jrx.anytxn.param.entity.PrBankInstInfo;
import com.jrx.anytxn.param.entity.PrBankInstInfoVo;
import com.jrx.anytxn.param.mapper.ext.ExtPrBankInstInfoMapper;
import com.jrx.anytxn.param.service.system.IBankInstInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 分支行-机构信息表 实现类
 *
 * @author Liuzb
 * @date 2022/04/21
 */
@Service
public class PrBankInstInfoServiceImpl implements IBankInstInfoService {

    private static Logger logger = LoggerFactory.getLogger(PrBankInstInfoServiceImpl.class);

    @Autowired
    private ExtPrBankInstInfoMapper extPrBankInstInfoMapper;

    @Autowired
    private ISegmentService segmentService;

    /**
     * 根据机构表编号查询同区域的所有支行信息
     *
     * @param bankInstInfo
     * @return
     */
    @Override
    public List<PrBankInstInfo> subBranchInfo(PrBankInstInfo bankInstInfo) throws TxnException {
        List<PrBankInstInfo> list = new ArrayList<>();
        Assert.hasLength(bankInstInfo.getTenantId(), "租户号不能为空");
        Assert.hasLength(bankInstInfo.getBankCode(), "支行（机构）编号不能为空");
        List<PrBankInstInfo> bankInstInfos = extPrBankInstInfoMapper.queryByBankCodeAndZone(bankInstInfo.getTenantId(), bankInstInfo.getBankCode(), null);
        if (!CollectionUtils.isEmpty(bankInstInfos)) {
            String zoneStr = bankInstInfos.get(0).getZoneStr();
            if (StringUtils.hasLength(zoneStr)) {
                List<PrBankInstInfo> bankInstInfoList = extPrBankInstInfoMapper.queryByBankCodeAndZone(bankInstInfo.getTenantId(), null, zoneStr);
                list.addAll(bankInstInfoList);
            } else {
                list.addAll(bankInstInfos);
            }
        }
        return list;
    }

    /**
     * 查询所有分行信息
     *
     * @return
     * @throws TxnException
     */
    @Override
    public List<PrBankInstInfo> branchInfo() throws TxnException {
        List<PrBankInstInfo> bankInstInfoList = extPrBankInstInfoMapper.queryAllBranchInfo();
        return bankInstInfoList;
    }

    /**
     * 根据租户ID和主键ID查询
     *
     * @param tenantId
     * @param id
     * @return
     */
    @Override
    public PrBankInstInfo getBankInstInfoById(String tenantId, String id) throws TxnException {
        Assert.hasLength(tenantId, "租户号不能为空");
        Assert.hasLength(id, "主键不能为空");
        PrBankInstInfo bankInstInfo = new PrBankInstInfo();
        bankInstInfo.setTenantId(tenantId);
        bankInstInfo.setId(Long.valueOf(id));
        List<PrBankInstInfo> bankInstInfos = extPrBankInstInfoMapper.queryByPrBankInstInfo(bankInstInfo);
        if (!CollectionUtils.isEmpty(bankInstInfos)) {
            return bankInstInfos.get(0);
        }
        return null;
    }

    /**
     * 新增分支行-机构信息
     *
     * @param bankInstInfo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public PrBankInstInfo addBankInstInfo(PrBankInstInfo bankInstInfo) throws TxnException {
        logger.info("addBankInstInfo参数：{}", JSONObject.toJSONString(bankInstInfo));
        Assert.hasLength(bankInstInfo.getTenantId(), "租户号不能为空");
        Assert.hasLength(bankInstInfo.getBankCode(), "支行（机构）编号不能为空");
        List<PrBankInstInfo> bankInstInfos = extPrBankInstInfoMapper.queryByBankCodeAndZone(bankInstInfo.getTenantId(), bankInstInfo.getBankCode(), null);
        if (CollectionUtils.isEmpty(bankInstInfos)) {
            try {
                bankInstInfo.setId(segmentService.getId(Constant.PR_BANK_INST_INFO));
            } catch (SegmentException e) {
                logger.error("主键生成错误", e);
                throw new TxnException(ErrorMsgConstant.ERROR_ID);
            }
            extPrBankInstInfoMapper.insertSelective(bankInstInfo);
        } else {
            logger.warn("该分支行-机构信息已存在，bankCode:{}", bankInstInfo.getBankCode());
            throw new RuntimeException("该分支行-机构信息已存在");
        }
        return bankInstInfo;
    }

    /**
     * 分页查询分支行-机构信息参数信息
     *
     * @param pageNum
     * @param pageSize
     * @param bankInstInfo
     * @return
     * @throws TxnException
     */
    @Override
    public TxnPage<PrBankInstInfo> findAllPageByTenantId(Integer pageNum, Integer pageSize, PrBankInstInfo bankInstInfo) throws TxnException {
        logger.info("findAllPageByTenantId查询参数：{}", JSONObject.toJSONString(bankInstInfo));
        Page<PrBankInstInfo> page = PageHelper.startPage(pageNum, pageSize, Constant.ORDER_BY_SORT);
        List<PrBankInstInfo> bankInstInfoList = extPrBankInstInfoMapper.queryByPrBankInstInfo(bankInstInfo);
        List<PrBankInstInfo> res = BeanMapping.copyList(bankInstInfoList, PrBankInstInfo.class);
        return new TxnPage<>(pageNum, pageSize, page.getTotal(), res);
    }

    /**
     * 修改分支行-机构信息
     *
     * @param bankInstInfo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public PrBankInstInfo modifyPrBankInstInfo(PrBankInstInfo bankInstInfo) throws TxnException {
        logger.info("modifyPrBankInstInfo参数：{}", JSONObject.toJSONString(bankInstInfo));
        String bankCode = bankInstInfo.getBankCode();
        Long id = bankInstInfo.getId();
        Assert.hasLength(bankInstInfo.getTenantId(), "租户号不能为空");
        Assert.hasLength(bankCode, "支行（机构）编号不能为空");
        if (Objects.isNull(bankInstInfo.getId())) {
            throw new RuntimeException("id不能为空");
        }
        PrBankInstInfo queryParam = new PrBankInstInfo();
        queryParam.setId(id);
        queryParam.setTenantId(bankInstInfo.getTenantId());
        List<PrBankInstInfo> list = extPrBankInstInfoMapper.queryByPrBankInstInfo(queryParam);
        // 主键存在的信息才需要修改
        if (!CollectionUtils.isEmpty(list)) {
            PrBankInstInfo prBankInstInfo = list.get(0);
            // 支行（机构）编号一致，直接修改信息
            if (prBankInstInfo.getBankCode().equals(bankCode)) {
                BeanUtils.copyProperties(bankInstInfo, prBankInstInfo);
                extPrBankInstInfoMapper.updateByPrBankInstInfo(prBankInstInfo);
            } else {
                queryParam.setId(null);
                queryParam.setBankCode(bankCode);
                // 修改了支行（机构）编号一致，需判断是已否存在该编号
                List<PrBankInstInfo> bankInstInfos = extPrBankInstInfoMapper.queryByPrBankInstInfo(queryParam);
                // 已经存在不允许修改
                if (!CollectionUtils.isEmpty(bankInstInfos)) {
                    logger.warn("该记录修改后的支行（机构）编号已有记录，不允许修改，id:{},bankCode:{}", id, bankCode);
                    throw new RuntimeException("该记录修改后的支行（机构）编号已有记录，不允许修改");
                } else {
                    // 修改后的支行（机构）编号不存在重复记录
                    BeanUtils.copyProperties(bankInstInfo, prBankInstInfo);
                    extPrBankInstInfoMapper.updateByPrBankInstInfo(prBankInstInfo);
                }
            }
        }
        return bankInstInfo;
    }

    /**
     * 根据ID删除信息
     *
     * @param tenantId
     * @param id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean removeByTenantIdAndId(String tenantId, String id) throws TxnException {
        logger.info("removeByTenantIdAndId参数：{}", id);
        Boolean deleteFlag = true;
        try {
            extPrBankInstInfoMapper.deleteByTenantIdAndId(tenantId, id);
        } catch (Exception e) {
            deleteFlag = false;
            logger.info("删除出错了");
        }
        return deleteFlag;
    }

    /**
     * 根据条件查找分支行信息
     *
     * @param bankInstInfo
     * @return
     */
    @Override
    public List<PrBankInstInfo> queryByPrBankInstInfo(PrBankInstInfo bankInstInfo) {
        logger.info("queryByPrBankInstInfo参数：{}", JSONObject.toJSONString(bankInstInfo));
        List<PrBankInstInfo> bankInstInfoList = extPrBankInstInfoMapper.queryByPrBankInstInfo(bankInstInfo);
        return bankInstInfoList;
    }

    /**
     * 根据银行代码查询上级分行信息
     * 若zoneStr与该行代码一致，代表该银行为分行级别，组装数据输出
     * 否则，查询该行的zonStr对应银行，再组装输出
     *
     * 循环最多执行两次
     *
     * @param bankInstInfo
     * @return
     */
    @Override
    public PrBankInstInfoVo queryLeaderBank(PrBankInstInfo bankInstInfo) throws TxnException {
        Assert.hasLength(bankInstInfo.getBankCode(), "银行代码不能为空");
        bankInstInfo.setTenantId("101");

        PrBankInstInfoVo prBankInstInfoVo = new PrBankInstInfoVo();
        PrBankInstInfo prBankInstInfo = null;
        prBankInstInfo = extPrBankInstInfoMapper.queryBankInfo(bankInstInfo);
        if (Objects.isNull(prBankInstInfo)) {
            throw new TxnException(TxnRespCode.BANK_NO_EXIT_ERROR);
        }
        prBankInstInfoVo.setCurrentName(prBankInstInfo.getName());//本级机构名称

        do {
            prBankInstInfo = extPrBankInstInfoMapper.queryBankInfo(bankInstInfo);
            if (Objects.isNull(prBankInstInfo)) {
                throw new TxnException(TxnRespCode.BANK_NO_EXIT_ERROR);
            }

            bankInstInfo.setBankCode(prBankInstInfo.getZoneStr());
        } while (!prBankInstInfo.getBankCode().equals(prBankInstInfo.getZoneStr()));

        prBankInstInfoVo.setBankCode(prBankInstInfo.getBankCode());//上级机构号
        prBankInstInfoVo.setBankName(prBankInstInfo.getName());//上级机构名称
        return prBankInstInfoVo;
    }
}
